﻿using CNI.Repostitory.Interface;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace CNI.Repository.Logger
{
    public class LoggerIngestion<T> : IIngestRepository<T>
    {
        static LoggerEventSource log;
        static LoggerEventListener listener;
        private static string Path { set; get; }

        public LoggerIngestion(string LogPath, string UniqueId)
        {
            Path = LogPath;
            log = LoggerEventSource.Logger;
            listener = new LoggerEventListener(LogPath, UniqueId);
            listener.EnableEvents(log, EventLevel.LogAlways);
        }

        public static void Dispose()
        {
            listener.Dispose();
        }

        public void Ingest(T Data)
        {
            log.LogString(JsonConvert.SerializeObject(Data));
        }
    }

    sealed public class LoggerEventSource : EventSource
    {
        [Event(1, Message = "{0}", Level = EventLevel.LogAlways)]
        public void LogString(string tel)
        {
            WriteEvent(1, tel);
        }

        public static LoggerEventSource Logger = new LoggerEventSource();
    }

    public class LoggerEventListener : EventListener
    {
        string rootPath = null;
        int numEvents = 0;
        int numEventGroups = 1;
        StreamWriter stream = null;
        string InstanceID = null;
        const int MAXEVENTS = 1000;

        public LoggerEventListener(string path, string uniqueId)
        {
            rootPath = path;
            InstanceID = uniqueId; 
            stream = NewStream();
        }

        protected override void OnEventWritten(EventWrittenEventArgs eventData)
        {
            numEvents++;

            Monitor.Enter(stream);
            try
            {
                if (eventData.EventId == 1)
                    stream.WriteLine(string.Format(eventData.Message, eventData.Payload[0]));

                if (numEvents > MAXEVENTS)
                {
                    stream.Flush();
                    stream.Close();
                    stream = NewStream();
                    numEvents = 0;
                    numEventGroups++;
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError("Exception calling OnEventWritten: {0}", ex.Message);
            }
            finally
            {
                Monitor.Exit(stream);
            }
        }

        StreamWriter NewStream()
        {

            string directory = Path.Combine(rootPath, "logs");
            if (!Directory.Exists(directory))
                Directory.CreateDirectory(directory);

            string filePath = Path.Combine(directory, String.Format("{1}-logdata-{0}.txt", DateTime.Now.Ticks, InstanceID));
            numEvents = 0;

            return new StreamWriter(filePath, true, System.Text.Encoding.UTF8, 10000);
        }

        public override void Dispose()
        {
            Trace.TraceInformation("LoggerEventListener:Dispose - dispose was called.");

            if (stream != null)
            {
                stream.Flush();
                stream.Close();
                stream = null;
            }
            base.Dispose();
        }
    }
}

